/*
 * @Description:
 * @Author: Cxy
 * @Date: 2024-03-20 15:07:32
 * @LastEditors: Cxy
 * @LastEditTime: 2024-03-21 22:20:43
 * @FilePath: \blogAdmin\play\src\hooks\Echarts.ts
 */

import * as echarts from 'echarts/core'
import { UniversalTransition } from 'echarts/features'
import { SVGRenderer } from 'echarts/renderers'
import { HeatmapChart, PieChart, RadarChart } from 'echarts/charts'
import {
  GridComponent,
  LegendComponent,
  TitleComponent,
  TooltipComponent,
  VisualMapComponent
} from 'echarts/components'
import type { HeatmapSeriesOption, PieSeriesOption, RadarSeriesOption } from 'echarts/charts'
import type {
  GraphicComponentOption,
  LegendComponentOption,
  TitleComponentOption,
  TooltipComponentOption,
  VisualMapComponentOption
} from 'echarts/components'
import type { ComposeOption } from 'echarts/core'
import type { Ref } from 'vue'
import { configStore } from '@/stores/config'

export type ECOption = ComposeOption<
  | GraphicComponentOption
  | TooltipComponentOption
  | VisualMapComponentOption
  | HeatmapSeriesOption
  | RadarSeriesOption
  | TitleComponentOption
  | LegendComponentOption
  | PieSeriesOption
>
echarts.use([
  GridComponent,
  SVGRenderer,
  UniversalTransition,
  TooltipComponent,
  VisualMapComponent,
  HeatmapChart,
  RadarChart,
  TitleComponent,
  LegendComponent,
  PieChart
])

export default function <T extends ECOption>(dom: Ref<HTMLElement>, oriOption: T) {
  const myChart: Ref<echarts.ECharts | null> = ref(null)
  const init = async () => {
    myChart.value = markRaw(
      echarts.init(dom.value, null, {
        renderer: 'svg'
      })
    )
    myChart.value.showLoading({
      color: 'rgb(var(--color-primary))',
      textColor: 'var(--color-text)',
      fontSize: 14,
      maskColor: 'var(--main-color-bg)'
    })
    myChart.value.setOption(oriOption)
  }

  const updateOption = (callback: (oriOption: T) => T) => {
    const option = callback(oriOption)
    myChart.value?.clear()
    myChart.value?.setOption(option)
    myChart.value?.hideLoading()
  }

  const resizeObserver = new ResizeObserver(() => {
    myChart.value?.resize()
  })

  function unMyChart() {
    myChart.value?.dispose()
    myChart.value = null
  }

  const darkLight = computed(() => configStore.config.darkLight)
  watch(darkLight, async () => {
    unMyChart()
    init()
    await new Promise(r => setTimeout(r, 500))
    myChart.value?.hideLoading()
  })

  onMounted(() => {
    if (!dom.value) throw 'echarts dom不存在'
    init()
    resizeObserver.observe(dom.value)
  })

  onBeforeUnmount(() => {
    unMyChart()
    resizeObserver.unobserve(dom.value)
  })

  return {
    myChart,
    updateOption
  }
}
